package com.louisgeek.myscanlogin.tool;

import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by louisgeek on 2018/8/27.
 */
public class IpManager {
    private Context mContext;
    private static final String TAG = "IpManager";
//    private List<String> mIpList = new ArrayList<>();

    public IpManager(Context context) {
        mContext = context;
    }

    private String ipPrefix;

    public void scanPort(final String ip) {
        //耗时任务
        Executors.newSingleThreadExecutor().execute(new Runnable() {
            @Override
            public void run() {
                Map<String, List<Integer>> ipMap = scanPortList(ip);
                Log.e(TAG, "run: 扫描端口结束");
            }
        });


    }

    private ExecutorService mExecutorServicePortScan = Executors.newFixedThreadPool(500);

    public Map<String, List<Integer>> scanPortList(final String ip) {
        final Map<String, List<Integer>> scanPortListMap = new HashMap<>();
        Log.e(TAG, ip + "端口开始扫描");
        //0 到 1023 系统使用
        //1024 到 65535
        for (int i = 1024; i <= 65535; i++) {
            final int finalI = i;
            mExecutorServicePortScan.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Socket socket = new Socket();
                        SocketAddress socketAddress = new InetSocketAddress(ip, finalI);
                        socket.connect(socketAddress, 50);
                        Log.e(TAG, ip + "端口扫描" + finalI);
                        //
                        List<Integer> portList = null;
                        if (!scanPortListMap.containsKey(ip)) {
                            portList = new ArrayList<>();
                            portList.add(finalI);
                            scanPortListMap.put(ip, portList);
                        } else {
                            portList = scanPortListMap.get(ip);
                            portList.add(finalI);
                        }
                        //
                        socket.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                        Log.e(TAG, e.getMessage());
                    }
                }
            });
        }
        //
        mExecutorServicePortScan.shutdown();
        //开始线程结束的循环监听 间隔0.5秒
        while (true) {
            if (mExecutorServicePortScan.isTerminated()) {// 扫描结束,开始验证
                return scanPortListMap;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }


    public interface ScanIpCallback {
        void backIpList(List<String> ipList);
    }

    public void scanIp(final ScanIpCallback scanIpCallback) {
        //
        ipPrefix = getLocAddrIndex();//获取本地ip前缀
        if (ipPrefix == null || "".equals(ipPrefix)) {
            UIToast.show(mContext, "扫描失败，请检查wifi网络");
            return;
        }
        //耗时任务
        Executors.newSingleThreadExecutor().execute(new Runnable() {
            @Override
            public void run() {
                List<String> ipList = scanIpList();
                if (scanIpCallback != null) {
                    scanIpCallback.backIpList(ipList);
                }
            }
        });

    }

    private List<String> scanIpList() {
        final List<String> ipList = new ArrayList<>();
        ExecutorService executorService = Executors.newFixedThreadPool(256);
        for (int i = 0; i < 256; i++) {
            final int finalI = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
//                    Log.e(TAG, "run: currentThread" + Thread.currentThread());
//                    checkIp();
                    String testIp = ipPrefix + finalI;
//                    pingIp(testIp);
                    boolean isReachable = pingIpRaw(testIp);
                    if (isReachable) {
                        ipList.add(testIp);
                    }
                }
            });
        }
        //
        executorService.shutdown();
        //开始线程结束的循环监听 间隔0.5秒
        while (true) {
            if (executorService.isTerminated()) {// 扫描结束,开始验证
                return ipList;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean pingIp(String ip) {
        boolean reachable = false;
        try {
            Log.e(TAG, "pingIp: " + ip);
            InetAddress address = InetAddress.getByName(ip);
            reachable = address.isReachable(6_000);
//            String hostName = address.getCanonicalHostName();
            if (reachable) {
                Log.e(TAG, "pingIp: reachable:" + ip);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reachable;
    }

    private boolean pingIpRaw(String ip) {
        boolean reachable = false;
        // -c 1 表示发送的次数，-w 6 表示发送后等待响应的时间[秒]
        String cmd = "ping -c 1 -w 6 " + ip;
        Log.e(TAG, "pingIpRaw: " + ip);
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(cmd);
            if (process.waitFor() == 0) {
                Log.e(TAG, "pingIpRaw: reachable:" + ip);
                reachable = true;

            } else {
                // UIToast.show(mContext, "连接失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        return reachable;
    }

    public void checkIpList(List<String> ipList) {
        ExecutorService executorService = Executors.newFixedThreadPool(ipList.size());
        for (final String ip : ipList) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    connectIp(ip);
                }
            });
        }
    }

    //向serversocket发送消息
    public String sendMsg(String ip) {

        String res = null;
        Socket socket = null;

        try {
            socket = new Socket(ip, 5555);
            //向服务器发送消息
            PrintWriter os = new PrintWriter(socket.getOutputStream());
            os.println("dsadasdas");
            os.flush();// 刷新输出流，使Server马上收到该字符串

            //从服务器获取返回消息
            DataInputStream input = new DataInputStream(socket.getInputStream());
            res = input.readUTF();
            System.out.println("server 返回信息：" + res);
//            Message.obtain(handler, 222, res).sendToTarget();//发送服务器返回消息

        } catch (Exception unknownHost) {
            System.out.println("You are trying to connect to an unknown host!");
        } finally {
            // 4: Closing connection
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return res;
    }

    public void connectIp(String ip) {
        Log.e(TAG, "connectIp: " + ip);
        OutputStream os = null;
        PrintWriter pw = null;
        //
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            Socket socket = new Socket(ip, 5555);
            if (socket.isConnected() && !socket.isClosed()) {
                // 发送数据
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write("check_ip" + "\n");
                pw.flush();
                //
                // 接收数据
                is = socket.getInputStream();
                socket.setSoTimeout(6_000);
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
                // 读取数据
                String info = br.readLine();
                if (info != null) {
                    Log.e(TAG, "zfq  run: info:" + info);
//                    mIpList.add(ip);
                }
                br.close();
                Log.e(TAG, "connectIp: " + ip);
                //
            } else {
                Log.e(TAG, "run: 链接已关闭");
                UIToast.show(mContext, "链接已关闭");
            }
        } catch (Exception e) {
            e.printStackTrace();
            UIToast.show(mContext, e.getMessage());
        }
    }

    //获取本地ip地址
    private static String getLocalHostAddress() {
        String ipAddress = "";
        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            // 遍历所用的网络接口
            while (en.hasMoreElements()) {
                NetworkInterface networks = en.nextElement();
                // 得到每一个网络接口绑定的所有ip
                Enumeration<InetAddress> address = networks.getInetAddresses();
                // 遍历每一个接口绑定的所有ip
                while (address.hasMoreElements()) {
                    InetAddress inetAddress = address.nextElement();
                    if (!inetAddress.isLoopbackAddress()
                            && inetAddress instanceof Inet4Address) {
                        ipAddress = inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            Log.e("", "获取本地ip地址失败");
            e.printStackTrace();
        }
        return ipAddress;

    }

    private static String getLocalIpAddress(Context context) {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        // 获取32位整型IP地址
        int ipAddress = wifiInfo.getIpAddress();
        // 返回整型地址转换成“*.*.*.*”地址
        return String.format("%d.%d.%d.%d", (ipAddress & 0xff),
                (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
                (ipAddress >> 24 & 0xff));
    }

    //获取IP前缀
    private String getLocAddrIndex() {

        String str = getLocalHostAddress();
//        String ipString = Formatter.formatIpAddress(ipAddress);
        if (!str.equals("")) {
            return str.substring(0, str.lastIndexOf(".") + 1);
        }

        return null;
    }


    //

    public class ScanPortRunnable implements Runnable {
        private String ip;
        private int minPort, maxPort;

        public ScanPortRunnable(String ip, int minPort, int maxPort) {
            this.minPort = minPort;
            this.maxPort = maxPort;
            this.ip = ip;
        }

        @Override
        public void run() {


        }
    }
}
